package com.rabbit.consumer;

import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class AddConsumer implements ChannelAwareMessageListener {
    //这个对应的是与“add”业务对应的消费者，有几个不同的业务对应几个不同的消费者，
    // 当然如果消息体里有区分不同业务的数据就无需这样做了，看具体业务场景可以灵活应对。
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        try {
            /**
             * 消费逻辑
             * 1.在内部多系统间调用可以使用feign调用其它业务，实现消费
             * 2.每次执行得并非同一个线程，consumerTag不一定一样，同一个consumerTag时deliverTag（从1开始）才会每个消息（包括重回队列的）增加1
             * 3.消费者可以通过消息内容中的appId和tenantId来实现多租户的管理，这里用map来接收，实际过程中可以根据具体业务封装一个实体类。
             */
            byte[] body = message.getBody();
            String s = new String(body, "utf-8");
            Map map = JSONObject.parseObject(s, Map.class);
            System.out.println("Reduce业务消费方消费了数据:  " + map);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            /**
             * 消费失败的逻辑
             * 方案之一：执行出现异常的逻辑时，可以选择先不确认，重回队列再次消费，但是如果执行多次还是失败可以先确认，将消息信息存入数据库，并记录日志。==具体还需结合自己的业务和具体异常来判断==
             * 分析：如何确保执行的次数: count？ 这个count应该是与消费异常的消息绑定的，随着消费异常而产生，随着消息最终消费成功或达到重复消费的次数被记录日志、数据库而消亡
             * 实现：可以简单封装Map,以消息的唯一标识（自己造）为键，以count为值，消费异常时生成键值对，成功或到达指定次数时可以销毁键值对
             * 注意：一定要确保消息会被确认，不然会导致消息一直无法消费，队列存储溢出。
             */
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            e.printStackTrace();
        }
    }
}
